import traceback

from flask import request, current_app as app
from app.errors import ParameterError
from functools import wraps


def param_input(schema, param='query', **v):
    """
    公共代码： 统一的参数校验装饰器
    目前只有request.args todo(request.json, request.form....)
    """
    def decorate(func):

        @wraps(func)
        def wrap(*args, **kwargs):
            try:
                if param == 'query':
                    req_args = dict(request.args)
                    schema_instance = schema(**req_args)
                    query = schema_instance.dict(**v)
                    kwargs.update({'query': query})
                elif param == 'json':
                    req_args = request.json
                    schema_instance = schema(**req_args)
                    query = schema_instance.dict(**v)
                    kwargs.update({'data': query})
                return func(*args, **kwargs)
            except ParameterError as e:
                raise ParameterError(msg=e.msg)
            except Exception as e:
                traceback.print_exc()
                raise ParameterError(msg="请检查参数")

        return wrap

    return decorate


def query_page_data(obj, query, resp_fields=None, page=None, count=None, sort=None):
    """公共代码： 翻页数据列表"""
    data = obj.find(query)
    total = data.count()  # 数据总量

    if sort:
        data = data.order_by(*sort)

    try:
        if resp_fields:
            data = data.only(*resp_fields)
    except Exception as e:
        app.logger.exception(e)
        traceback.print_exc()
        raise ParameterError(msg='请检查返回字段')

    data = data.paginate(page, count)
    data = list(data.items.as_pymongo())
    return data, total


def query_data(obj, query, resp_fields=None, sort=None):
    """公共代码： 数据筛选与返回"""
    data = obj.find(query)
    total = data.count()  # 数据总量

    if sort:
        data = data.order_by(*sort)

    data = list({k: getattr(i, k, None) for k in resp_fields} for i in data)
    return data, total
